using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using ExamPaperEditingSystem.Models;
using ExamPaperEditingSystem.Services;
using ExamPaperEditingSystem.Utils;
using static ExamPaperEditingSystem.Models.QuestionType;
using Microsoft.Win32;

namespace ExamPaperEditingSystem.ViewModels
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private readonly IEmbeddingService _embeddingService;
        private readonly IChatService _chatService;
        private readonly IVectorDatabaseService _vectorDatabaseService;
        private readonly IKnowledgeGraphService _knowledgeGraphService;
        private readonly IDocumentProcessorService _documentProcessorService;
        private readonly IExamPaperService _examPaperService;

        private string _currentMessage = string.Empty;
        private string _selectedKnowledgeBase = string.Empty;
        private bool _isProcessing = false;
        private bool _showThinkingChain = false;
        private string _statusMessage = "就绪";
        private ExamPaper? _currentExamPaper;

        public MainWindowViewModel(
            IEmbeddingService embeddingService,
            IChatService chatService,
            IVectorDatabaseService vectorDatabaseService,
            IKnowledgeGraphService knowledgeGraphService,
            IDocumentProcessorService documentProcessorService,
            IExamPaperService examPaperService)
        {
            _embeddingService = embeddingService;
            _chatService = chatService;
            _vectorDatabaseService = vectorDatabaseService;
            _knowledgeGraphService = knowledgeGraphService;
            _documentProcessorService = documentProcessorService;
            _examPaperService = examPaperService;

            ChatMessages = new ObservableCollection<ChatMessage>();
            KnowledgeBases = new ObservableCollection<string>();
            ExamPapers = new ObservableCollection<ExamPaper>();

            InitializeCommands();
            LoadKnowledgeBases();
            LoadExamPapers();
        }

        #region Properties

        public ObservableCollection<ChatMessage> ChatMessages { get; }
        public ObservableCollection<string> KnowledgeBases { get; }
        public ObservableCollection<ExamPaper> ExamPapers { get; }

        public string CurrentMessage
        {
            get => _currentMessage;
            set
            {
                _currentMessage = value;
                OnPropertyChanged();
                ((RelayCommand)SendMessageCommand).RaiseCanExecuteChanged();
            }
        }

        public string SelectedKnowledgeBase
        {
            get => _selectedKnowledgeBase;
            set
            {
                _selectedKnowledgeBase = value;
                OnPropertyChanged();
            }
        }

        public bool IsProcessing
        {
            get => _isProcessing;
            set
            {
                _isProcessing = value;
                OnPropertyChanged();
                ((RelayCommand)SendMessageCommand).RaiseCanExecuteChanged();
            }
        }

        public bool ShowThinkingChain
        {
            get => _showThinkingChain;
            set
            {
                _showThinkingChain = value;
                OnPropertyChanged();
            }
        }

        public string StatusMessage
        {
            get => _statusMessage;
            set
            {
                _statusMessage = value;
                OnPropertyChanged();
            }
        }

        public ExamPaper? CurrentExamPaper
        {
            get => _currentExamPaper;
            set
            {
                _currentExamPaper = value;
                OnPropertyChanged();
            }
        }

        private bool _isOnlineMode = true;
        public bool IsOnlineMode
        {
            get => _isOnlineMode;
            set
            {
                _isOnlineMode = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(ApiModeText));
            }
        }

        public string ApiModeText => IsOnlineMode ? "在线模式" : "本地模式";

        #endregion

        #region Commands

        public ICommand SendMessageCommand { get; private set; } = null!;
        public ICommand ImportDocumentsCommand { get; private set; } = null!;
        public ICommand CreateKnowledgeBaseCommand { get; private set; } = null!;
        public ICommand CopyMessageCommand { get; private set; } = null!;
        public ICommand CreateExamPaperCommand { get; private set; } = null!;
        public ICommand SaveExamPaperCommand { get; private set; } = null!;
        public ICommand ExportExamPaperCommand { get; private set; } = null!;
        public ICommand ClearChatCommand { get; private set; } = null!;
        public ICommand ToggleThinkingCommand { get; private set; } = null!;
        public ICommand LoadExamPaperCommand { get; private set; } = null!;
        public ICommand DeleteKnowledgeBaseCommand { get; private set; } = null!;
        public ICommand AddQuestionCommand { get; private set; } = null!;

        #endregion

        private void InitializeCommands()
        {
            SendMessageCommand = new RelayCommand(async () => await SendMessageAsync(), () => !IsProcessing && !string.IsNullOrWhiteSpace(CurrentMessage));
            ImportDocumentsCommand = new RelayCommand(async () => await ImportDocumentsAsync());
            CreateKnowledgeBaseCommand = new RelayCommand(async () => await CreateKnowledgeBaseAsync());
            CopyMessageCommand = new RelayCommand<ChatMessage>(CopyMessage);
            CreateExamPaperCommand = new RelayCommand(CreateExamPaper);
            SaveExamPaperCommand = new RelayCommand(async () => await SaveExamPaperAsync(), () => CurrentExamPaper != null);
            ExportExamPaperCommand = new RelayCommand(async () => await ExportExamPaperAsync(), () => CurrentExamPaper != null);
            ClearChatCommand = new RelayCommand(ClearChat);
            ToggleThinkingCommand = new RelayCommand<ChatMessage>(ToggleThinking);
            LoadExamPaperCommand = new RelayCommand(async () => await LoadExamPaperAsync());
            DeleteKnowledgeBaseCommand = new RelayCommand(async () => await DeleteKnowledgeBaseAsync());
            AddQuestionCommand = new RelayCommand(AddQuestion, () => CurrentExamPaper != null);
        }

        #region Methods

        private async Task SendMessageAsync()
        {
            if (string.IsNullOrWhiteSpace(CurrentMessage) || IsProcessing)
                return;

            var userMessage = new ChatMessage
            {
                Content = CurrentMessage,
                Role = "user",
                Timestamp = DateTime.Now
            };

            ChatMessages.Add(userMessage);
            var messageToSend = CurrentMessage;
            CurrentMessage = string.Empty;
            IsProcessing = true;
            StatusMessage = "正在处理...";

            try
            {
                // 如果选择了知识库，进行相关性搜索
                string contextualMessage = messageToSend;
                if (!string.IsNullOrEmpty(SelectedKnowledgeBase))
                {
                    var searchResults = await _vectorDatabaseService.SearchAsync(SelectedKnowledgeBase, messageToSend, 5);
                    if (searchResults.Any())
                    {
                        var context = string.Join("\n\n", searchResults.Select(r => r.Document.Content));
                        contextualMessage = $"基于以下知识库内容回答问题：\n\n{context}\n\n问题：{messageToSend}";
                    }
                }

                var assistantMessage = new ChatMessage
                {
                    Content = "",
                    Role = "assistant",
                    Timestamp = DateTime.Now
                };

                ChatMessages.Add(assistantMessage);

                // 流式接收响应
                var response = await _chatService.StreamMessageAsync(contextualMessage, ChatMessages.ToList());
                
                // 模拟流式响应
                foreach (var chunk in response.Split(' '))
                {
                    if (!string.IsNullOrEmpty(chunk))
                    {
                        // 检查是否包含思维链
                        if (chunk.Contains("<thinking>") || chunk.Contains("</thinking>"))
                        {
                            assistantMessage.IsThinking = true;
                            assistantMessage.ThinkingContent += chunk + " ";
                        }
                        else
                        {
                            assistantMessage.Content += chunk + " ";
                        }
                        OnPropertyChanged(nameof(ChatMessages));
                        await Task.Delay(50); // 模拟打字效果
                    }
                }

                // 提取并移除思维链
                var finalContent = _chatService.RemoveThinkingContent(assistantMessage.Content + assistantMessage.ThinkingContent);
                var thinkingContent = _chatService.ExtractThinkingContent(assistantMessage.Content + assistantMessage.ThinkingContent);

                assistantMessage.Content = finalContent;
                assistantMessage.ThinkingContent = thinkingContent;
                assistantMessage.IsThinking = !string.IsNullOrEmpty(thinkingContent);

                StatusMessage = "完成";
            }
            catch (Exception ex)
            {
                var errorMessage = new ChatMessage
                {
                    Content = $"错误：{ex.Message}",
                    Role = "system",
                    Timestamp = DateTime.Now
                };
                ChatMessages.Add(errorMessage);
                StatusMessage = "发生错误";
            }
            finally
            {
                IsProcessing = false;
            }
        }

        private async Task ImportDocumentsAsync()
        {
            var openFileDialog = new OpenFileDialog
            {
                Title = "选择要导入的文档",
                Filter = "支持的文档|*.txt;*.docx;*.pptx;*.xlsx;*.xls|所有文件|*.*",
                Multiselect = true
            };

            if (openFileDialog.ShowDialog() == true)
            {
                IsProcessing = true;
                StatusMessage = "正在处理文档...";

                try
                {
                    await Task.Run(() =>
                    {
                        var targetDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exam courseware");
                        Directory.CreateDirectory(targetDir);

                        foreach (var filePath in openFileDialog.FileNames)
                        {
                            var fileName = Path.GetFileName(filePath);
                            var targetPath = Path.Combine(targetDir, fileName);
                            File.Copy(filePath, targetPath, true);
                        }
                    });

                    StatusMessage = $"已导入 {openFileDialog.FileNames.Length} 个文档";
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"导入文档时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    StatusMessage = "导入失败";
                }
                finally
                {
                    IsProcessing = false;
                }
            }
        }

        private async Task CreateKnowledgeBaseAsync()
        {
            var dialog = new Microsoft.Win32.SaveFileDialog
            {
                Title = "创建知识库",
                Filter = "知识库文件|*.kb",
                DefaultExt = "kb"
            };

            if (dialog.ShowDialog() == true)
            {
                var kbName = Path.GetFileNameWithoutExtension(dialog.FileName);
                IsProcessing = true;
                StatusMessage = "正在创建知识库...";

                try
                {
                    await _vectorDatabaseService.CreateKnowledgeBaseAsync(kbName, $"知识库：{kbName}");

                    var coursewareDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exam courseware");
                    if (Directory.Exists(coursewareDir))
                    {
                        var files = Directory.GetFiles(coursewareDir, "*.*", SearchOption.AllDirectories)
                            .Where(f => new[] { ".txt", ".docx", ".pptx", ".xlsx", ".xls" }
                                .Contains(Path.GetExtension(f).ToLower()))
                            .ToArray();

                        var documents = await _documentProcessorService.ProcessDocumentsAsync(coursewareDir, kbName);
                        
                        foreach (var doc in documents)
                        {
                            await _vectorDatabaseService.AddDocumentAsync(kbName, doc);
                        }
                    }

                    LoadKnowledgeBases();
                    StatusMessage = $"知识库 '{kbName}' 创建完成";
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"创建知识库时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    StatusMessage = "创建失败";
                }
                finally
                {
                    IsProcessing = false;
                }
            }
        }

        private void CopyMessage(ChatMessage? message)
        {
            if (message != null)
            {
                var formattedContent = message.Content;
                Clipboard.SetText(formattedContent);
                StatusMessage = "已复制到剪贴板";
            }
        }

        private void CreateExamPaper()
        {
            CurrentExamPaper = new ExamPaper
            {
                Id = Guid.NewGuid().ToString(),
                Title = "新试卷",
                Subject = "",
                CreatedAt = DateTime.Now,
                Questions = new List<ExamQuestion>()
            };

            ExamPapers.Add(CurrentExamPaper);
            StatusMessage = "已创建新试卷";
        }

        private void AddQuestion()
        {
            if (CurrentExamPaper == null) return;

            var newQuestion = new ExamQuestion
            {
                Id = Guid.NewGuid().ToString(),
                QuestionNumber = CurrentExamPaper.Questions.Count + 1,
                Type = SingleChoice,
                Content = "请输入题目内容...",
                Answer = "请输入答案...",
                Explanation = "请输入解析...",
                Score = 5
            };

            CurrentExamPaper.Questions.Add(newQuestion);
            StatusMessage = $"已添加第 {newQuestion.QuestionNumber} 题";

            // 触发属性更改通知以更新UI
            OnPropertyChanged(nameof(CurrentExamPaper));
        }

        private async Task SaveExamPaperAsync()
        {
            if (CurrentExamPaper == null) return;

            try
            {
                await _examPaperService.SaveExamPaperAsync(CurrentExamPaper);
                StatusMessage = "试卷已保存";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存试卷时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                StatusMessage = "保存失败";
            }
        }

        private async Task ExportExamPaperAsync()
        {
            if (CurrentExamPaper == null) return;

            try
            {
                await _examPaperService.ExportToWordAsync(CurrentExamPaper);
                StatusMessage = "试卷已导出为Word文档";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导出试卷时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                StatusMessage = "导出失败";
            }
        }

        private void ClearChat()
        {
            ChatMessages.Clear();
            StatusMessage = "聊天记录已清空";
        }

        private void ToggleThinking(ChatMessage? message)
        {
            if (message != null && message.IsThinking)
            {
                message.IsThinkingExpanded = !message.IsThinkingExpanded;
            }
        }

        private void LoadKnowledgeBases()
        {
            try
            {
                var kbDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vector Knowledge Base");
                if (Directory.Exists(kbDir))
                {
                    KnowledgeBases.Clear();
                    var kbFiles = Directory.GetFiles(kbDir, "*.json")
                        .Select(f => Path.GetFileNameWithoutExtension(f))
                        .ToArray();

                    foreach (var kb in kbFiles)
                    {
                        KnowledgeBases.Add(kb);
                    }
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"加载知识库列表失败：{ex.Message}";
            }
        }

        private async void LoadExamPapers()
        {
            try
            {
                var papers = await _examPaperService.GetAllExamPapersAsync();
                ExamPapers.Clear();
                foreach (var paper in papers)
                {
                    ExamPapers.Add(paper);
                }
            }
            catch (Exception ex)
            {
                StatusMessage = $"加载试卷列表失败：{ex.Message}";
            }
        }

        private async Task LoadExamPaperAsync()
        {
            var openFileDialog = new OpenFileDialog
            {
                Title = "选择要加载的试卷文件",
                Filter = "Word文档|*.docx|所有文件|*.*"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                IsProcessing = true;
                StatusMessage = "正在加载试卷...";

                try
                {
                    var examPaper = await _examPaperService.ImportFromWordAsync(openFileDialog.FileName);
                    CurrentExamPaper = examPaper;
                    ExamPapers.Add(examPaper);
                    StatusMessage = "试卷加载完成";
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"加载试卷时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    StatusMessage = "加载失败";
                }
                finally
                {
                    IsProcessing = false;
                }
            }
        }

        private async Task DeleteKnowledgeBaseAsync()
        {
            if (string.IsNullOrEmpty(SelectedKnowledgeBase))
            {
                MessageBox.Show("请先选择要删除的知识库", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            var result = MessageBox.Show($"确定要删除知识库 '{SelectedKnowledgeBase}' 吗？\n此操作不可撤销。", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            if (result == MessageBoxResult.Yes)
            {
                IsProcessing = true;
                StatusMessage = "正在删除知识库...";

                try
                {
                    await _vectorDatabaseService.DeleteKnowledgeBaseAsync(SelectedKnowledgeBase);
                    LoadKnowledgeBases();
                    SelectedKnowledgeBase = string.Empty;
                    StatusMessage = "知识库删除完成";
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"删除知识库时发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    StatusMessage = "删除失败";
                }
                finally
                {
                    IsProcessing = false;
                }
            }
        }

        private async Task InitializeAsync()
        {
            try
            {
                StatusMessage = "正在初始化...";
                // 这里可以添加初始化逻辑
                await Task.Delay(100); // 模拟初始化过程
                StatusMessage = "就绪";
            }
            catch (Exception ex)
            {
                StatusMessage = $"初始化失败：{ex.Message}";
            }
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler? PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
        {
            if (Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        #endregion
    }
}